/**
 ****************************************************************************************************
 * @file        esp_2d.h
 * @author      嵌入式小书虫
 * @version     V1.0
 * @date        2020-04-17
 * @brief       esp_2d 驱动代码
 ****************************************************************************************************
 *
 * 修改说明
 * V1.0 20200417
 * 第一次发布
 <欢迎关注微信公众号：嵌入式小书虫>
 *
 ****************************************************************************************************
 */

#ifndef _ESP_2D_H
#define _ESP_2D_H

#include "./BSP/LCD/lcd.h"

#include<string.h>
#include<stdbool.h>

#define ESP_2D_LCD_WIDTH   320
#define ESP_2D_LCD_HEIGHT  240

#define ESP_2D_PFB_WIDTH   10
#define ESP_2D_PFB_HEIGHT  10
#define ESP_2D_PFB_SIZE  (ESP_2D_PFB_WIDTH * ESP_2D_PFB_HEIGHT)

#define  ESP_2D_DIRTY_REGIONS_ENABLE  1
#define  ESP_2D_NAVIGATION_SCENE_ENABLE 1 
#define  ALL_SCREEN_ROW_PRIORITY 0

#define __ESP_2D_RGB(__R, __G, __B)    ((((uint16_t)(__R) & 0xFF) >> 3 << 11)   |   \
                                    (((uint16_t)(__G) & 0xFF) >> 2 << 5)    |   \
                                    (((uint16_t)(__B) & 0xFF) >> 3 << 0)    )

/* GLCD RGB color definitions                            */
#define ESP_2D_GLCD_COLOR_BLACK        __ESP_2D_RGB(   0,   0,   0  )
#define ESP_2D_GLCD_COLOR_NAVY         __ESP_2D_RGB(   0,   0, 128  )
#define ESP_2D_GLCD_COLOR_DARK_GREEN   __ESP_2D_RGB(   0, 128,   0  )
#define ESP_2D_GLCD_COLOR_DARK_CYAN    __ESP_2D_RGB(   0, 128, 128  )
#define ESP_2D_GLCD_COLOR_MAROON       __ESP_2D_RGB( 128,   0,   0  )
#define ESP_2D_GLCD_COLOR_PURPLE       __ESP_2D_RGB( 128,   0, 128  )
#define ESP_2D_GLCD_COLOR_OLIVE        __ESP_2D_RGB( 128, 128,   0  )
#define ESP_2D_GLCD_COLOR_LIGHT_GREY   __ESP_2D_RGB( 192, 192, 192  )
#define ESP_2D_GLCD_COLOR_DARK_GREY    __ESP_2D_RGB( 128, 128, 128  )
#define ESP_2D_GLCD_COLOR_BLUE         __ESP_2D_RGB(   0,   0, 255  )
#define ESP_2D_GLCD_COLOR_GREEN        __ESP_2D_RGB(   0, 255,   0  )
#define ESP_2D_GLCD_COLOR_CYAN         __ESP_2D_RGB(   0, 255, 255  )
#define ESP_2D_GLCD_COLOR_RED          __ESP_2D_RGB( 255,   0,   0  )
#define ESP_2D_GLCD_COLOR_MAGENTA      __ESP_2D_RGB( 255,   0, 255  )
#define ESP_2D_GLCD_COLOR_YELLOW       __ESP_2D_RGB( 255, 255, 0    )
#define ESP_2D_GLCD_COLOR_WHITE        __ESP_2D_RGB( 255, 255, 255  )


typedef enum {
    esp_2d_fsm_rt_err          = -1,    // fsm error
    esp_2d_fsm_rt_cpl          = 0,     // complete
    esp_2d_fsm_rt_on_going     = 1,     // on-going
    esp_2d_fsm_rt_wait_for_obj = 2,     // fsm wait for IPC object
    esp_2d_fsm_rt_async        = 3,     // fsm work asynchronously, please check it later.
    esp_2d_fsm_rt_wait_for_res = 4,     // wait for resource
} esp_2d_fsm_rt_t;



 
 typedef struct esp_2d_size_t {
    int16_t iWidth;                     //  width of an rectangular area
    int16_t iHeight;                    //  height of an rectangular area
} esp_2d_size_t;
typedef struct esp_2d_location_t {
    int16_t iX;                         //!< x in Cartesian coordinate system
    int16_t iY;                         //!< y in Cartesian coordinate system
} esp_2d_location_t;
 
typedef struct esp_2d_region_t {
    esp_2d_location_t tLocation;//implement_ex(arm_2d_location_t, tLocation); //!< the location (top-left corner)
    esp_2d_size_t   tSize;//implement_ex(arm_2d_size_t, tSize);         //!< the size
} esp_2d_region_t;
 
typedef struct esp_2d_op_fill_cl_t{
    char i;
}esp_2d_op_fill_cl_t;


typedef struct esp_2d_tile_t esp_2d_tile_t;
struct esp_2d_tile_t {
                                        //!< the region of the tile
    esp_2d_region_t  tRegion;
    union {
        uint8_t             *pchBuffer;                                         //!< a pointer points to a buffer in a 8bit colour type
        uint16_t            *phwBuffer;                                         //!< a pointer points to a buffer in a 16bit colour type
        uint32_t            *pwBuffer;                                          //!< a pointer points to a buffer in a 32bit colour type

        intptr_t            nAddress;                                           //!< a pointer in integer
    };
};

/******************************************************************************************/

 
typedef struct esp_2d_scene esp_2d_scene_t;

struct esp_2d_op_t2{
    int16_t state;
    esp_2d_scene_t *scene;
#if ESP_2D_NAVIGATION_SCENE_ENABLE  
    
    esp_2d_scene_t *navigation_scene;
    
#endif
    
    uint16_t pfb_data[ESP_2D_PFB_SIZE];
    esp_2d_region_t pfb_region;
    
    uint8_t background_draw_flag;
#if ESP_2D_DIRTY_REGIONS_ENABLE  
    
    esp_2d_region_t* ptDirtyRegions;
    uint8_t DirtyRegions_num;
    uint8_t DirtyRegions_run_num;
    uint8_t Row_priority_flag ;
    
#endif
    //my2d_size_t pfb_size;
    
    //int16_t ix_num;
    //int16_t iy_num;
    
    //============
    //my2d_tile_t *pTarget;
    //my2d_tile_t *ptTile;
    bool bIsNewFrame;

};
typedef struct{
    uint8_t *pchBuffer;
    uint16_t offset;
    uint16_t char_width;
    uint8_t WidthOffset;
    esp_2d_size_t   tSize;
}esp_2d_font_tile_t;

typedef struct esp_2d_op_t2 esp_2d_op_t;
extern esp_2d_op_t esp_2d_op0;



typedef esp_2d_fsm_rt_t esp_2d_helper_draw_handler_t( 
                                          esp_2d_op_t* pt_esp_2d_op,
                                          bool bIsNewFrame);
struct esp_2d_scene{
    void (*fnOnLoad)(esp_2d_op_t* pt_esp_2d_op,struct esp_2d_scene *ptScene);
    //void (*fnOnLoad)(arm_2d_scene_t *ptThis);                                   //!< on load event handler
    void (*fnOnBGStart)(esp_2d_op_t* pt_esp_2d_op,struct esp_2d_scene *ptThis);                                //!< on-start-drawing-background event handler
    void (*fnOnBGComplete)(esp_2d_op_t* pt_esp_2d_op,struct esp_2d_scene *ptThis);                             //!< on-complete-drawing-background event handler
    void (*fnOnFrameStart)(esp_2d_op_t* pt_esp_2d_op,struct esp_2d_scene *ptThis);                             //!< on-frame-start event handler
    void (*fnOnFrameCPL)(esp_2d_op_t* pt_esp_2d_op,struct esp_2d_scene *ptThis);                               //!< on-frame-complete event handler
    esp_2d_helper_draw_handler_t *fnScene;
};

#define ESP_2D_SCENE  get_esp_2d_op(),get_esp_2d_op()->scene

void esp_2d_init();
esp_2d_op_t* get_esp_2d_op();
void __esp_2d_init(esp_2d_op_t* pt_esp_2d_op);
void esp_2d_disp_adapter0_task();
//esp_2d_fsm_rt_t esp_2d_scene_player_task();
esp_2d_fsm_rt_t esp_2d_scene_player_task(esp_2d_op_t *pt_esp_2d_op);
esp_2d_fsm_rt_t __esp_2d_disp_adapter0_task(void);



void esp_2d_Disp0_DrawBitmap (uint32_t x, 
                         uint32_t y, 
                         uint32_t width, 
                         uint32_t height, 
                         const uint8_t *bitmap);
//=======================================================================================


#endif
